<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>04_高阶函数与函数柯里化</title>
</head>
<body>
<!-- 
应用需求:
  1. 根据指定的数据对象来动态显示姓名和年龄
  2. 当姓名或年龄输入时, 实时保存到数据对象中, 并输出
-->
姓名: <input type="text" id="name"><br>
年龄: <input type="text" id="age"><br>


<script>
  const p = {
    name: 'tom',
    age: 12
  }

  /*   
  p.name = 'xxx'
  var propName = 'name'
  p[propName] = 'yyy'
  propName = 'age'
  p[propName] = 23 */

  // 得到输入框 
  const nameInput = document.getElementById('name')
  const ageInput = document.getElementById('age')
  // 指定对应的value
  nameInput.value = p.name
  ageInput.value = p.age

  /* 
  propName是由我们来指定, 可能是'name', 也可能是'age', 在绑定事件监听时就可以指定
  event 在事件触发时, 由浏览器来指定

  要做一件事, 需要的2个条件数据, 
    一个(propName)是由我们来先确定
    另一个(event)后面由浏览器决定
  */
 // 问题: 定义一个接收2个条件参数的函数 不能实现
  function handle(event, propName) {
    console.log('handle', propName)
    p[propName] = event.target.value
    console.log(p)
  }

  // 解决: 使用柯里化函数来处理
  function handle2(propName) {
    return function (event) {
      p[propName] = event.target.value
      console.log(p)
    }
  }

  // 给input标签绑定input事件(输入发生改变时触发), 在回调中读取输入的值, 保存到p中
  /* nameInput.oninput = function (event) {
    p.name = event.target.value
    console.log(p)
  }
  ageInput.oninput = function (event) {
    p.age = event.target.value
    console.log(p)
  } */
  nameInput.oninput = handle2('name')   // 需要指定的是name
  ageInput.oninput = handle2('age')   // 需要指定的是age

</script>




<script>
  /* 
  高阶函数: 只要满足下面其中一条就是
    1. 接收的参数是函数
      数组遍历相关方法: forEach/filter/map/reduce/find/findIndex/some/every
      定时器: setTimeout / setInterval
      Promise/ then
    2. 返回值是函数
      bind
      闭包的外部函数
    高阶函数的优点: 更加动态/扩展能力更强
      接收一个函数, 就意味着接收一个动态的功能
      返回一个函数, 外部就可以接收到它, 通过调用它来操作外部函数内部的局部变量
  函数柯里化
  */
 // 命令式编程: 所有的事都得亲自做

  // const result = []
  // const arr = [1, 3, 5]
  // for (let index = 0; index < arr.length; index++) {
  //   const element = arr[index];
  //   if (element>2) {
  //     result.push(element)
  //   }
  // }
  // console.log(result) // [3, 5]
  // // 声明式编程: 做部分不确定的工作, 通过函数参数的形式传递给filter
  // const result2 = arr.filter(item => item>2) 

  // function fn1() {
  //   var a = 2
  //   function fn2() {
  //     a++
  //     console.log(a)
  //   }
  //   return fn2
  // }
  // const fn = fn1()
  // fn()
  // fn()
</script>

<script>
  /* 
  函数柯里化
    将一个函数的多参数改造为一个参数多次传递的函数来实现功能
    惰性求值: 开始指定一个条件数据时不进行计算处理, 
              只有等到所有条件数据指定好后, 才进行计算处理返回结果值
    柯里化函数是一个高阶函数
  */

  function sum(a, b, c) {
    return a + b + c
  }
  // console.log(sum(2, 3, 4))

  function sum2(a) {
    return function (b) {
      return function (c) {
        return a + b + c
      }
    }
  }
  // console.log(sum2(2)(3)(4))
</script>
</body>
</html>